import React, { useState, useEffect } from 'react';
import { Form, Input, Select, Button, message } from 'antd';
import { clone as cloneDeep } from 'ramda';
import { ElementType, FlowVariableType } from '../../config';
import ApiSelect from '../form/ApiSelect';
import OutputRuleSetting from '../form/OutputRuleSetting';
import InputRuleSetting from '../form/InputRuleSetting';
import { apiService, suiteService } from '@/flowService';
import useFlowStore from '../../hooks/flowStore';

const { TextArea } = Input;

const MethodForm = ({ data, onUpdate, onCancel }) => {
  const [form] = Form.useForm();
  const [nodeData, setNodeData] = useState(getDefaultData());
  const [suiteList, setSuiteList] = useState([]);
  const [suiteLoading, setSuiteLoading] = useState(false);
  const [headerSourceList, setHeaderSourceList] = useState([]);
  const [inputSourceList, setInputSourceList] = useState([]);
  const [outputSourceList, setOutputSourceList] = useState([]);
  const [headerRequiredKeys, setHeaderRequiredKeys] = useState([]);
  const [inputRequiredKeys, setInputRequiredKeys] = useState([]);
  const flowContext = useFlowStore();

  function getDefaultData() {
    return {
      key: '',
      name: '',
      outgoings: [],
      incomings: [],
      elementType: ElementType.METHOD,
      desc: '',
      method: {
        methodCode: null,
        suiteCode: null,
        url: '',
        requestType: '',
        requestContentType: '',
        inputParamSchemas: [],
        headerFillRules: [],
        inputFillRules: [],
        outputFillRules: [],
      },
    };
  }

  useEffect(() => {
    if (data) {
      const newData = Object.assign(getDefaultData(), cloneDeep(data));
      setNodeData(newData);
      if (newData.method.methodCode) {
        initApiSourceList(newData.method.methodCode);
      }
    }
  }, [data]);

  useEffect(() => {
    querySuiteList();
  }, []);

  const inputTargetList = flowContext.data.flowVariables.filter(
    (item) => [FlowVariableType.INPUT, FlowVariableType.TEMP].includes(item.envType)
  );

  const outputTargetList = flowContext.data.flowVariables.filter(
    (item) => [FlowVariableType.OUTPUT, FlowVariableType.TEMP].includes(item.envType)
  );

  function paramToRule(param, sourceType) {
    return {
      source: '',
      sourceDataType: null,
      sourceType: 'VARIABLE',
      target: param.paramKey,
      targetDataType: param.dataType,
      targetType: sourceType,
      required: true,
    };
  }

  async function initApiSourceList(apiCode) {
    const res = await apiService.queryApiInfoByCode(apiCode);
    if (res.result) {
      const result = res.result;
      setHeaderSourceList(result.apiHeaders.map(item => ({ ...item, targetType: 'HEADER' })));
      setInputSourceList(result.apiInputParams.map(item => ({ ...item, targetType: 'INPUT_PARAM' })));
      setOutputSourceList(result.apiOutputParams.map(item => ({ ...item, sourceType: 'OUTPUT_PARAM' })));

      const headerRequired = result.apiHeaders.filter(item => item.required);
      setHeaderRequiredKeys(headerRequired.map(item => item.paramKey));

      const inputRequired = result.apiInputParams.filter(item => item.required);
      setInputRequiredKeys(inputRequired.map(item => item.paramKey));
    }
  }

  function onSuiteChange(suiteCode) {
    setNodeData({
      ...nodeData,
      method: {
        ...getDefaultData().method,
        suiteCode: suiteCode,
      },
    });
  }

  async function onApiChange(apiCode) {
    const res = await apiService.queryApiInfoByCode(apiCode);
    if (res.result) {
      const result = res.result;
      const method = {
        ...nodeData.method,
        requestType: result.apiRequestType,
        requestContentType: result.apiRequestContentType,
        inputParamSchemas: result.apiInputParams.map((item) => ({
          key: item.paramKey,
          name: item.paramName,
          dataType: item.dataType,
          position: item.paramPosition,
        })),
        url: result.apiUrl,
      };

      setHeaderSourceList(result.apiHeaders.map(item => ({ ...item, targetType: 'HEADER' })));
      setInputSourceList(result.apiInputParams.map(item => ({ ...item, targetType: 'INPUT_PARAM' })));
      setOutputSourceList(result.apiOutputParams.map(item => ({ ...item, sourceType: 'OUTPUT_PARAM' })));

      const headerRequired = result.apiHeaders.filter(item => item.required);
      method.headerFillRules = headerRequired.map(item => paramToRule(item, 'HEADER'));
      setHeaderRequiredKeys(headerRequired.map(item => item.paramKey));

      const inputRequired = result.apiInputParams.filter(item => item.required);
      method.inputFillRules = inputRequired.map(item => paramToRule(item, 'INPUT_PARAM'));
      setInputRequiredKeys(inputRequired.map(item => item.paramKey));

      method.outputFillRules = [];
      setNodeData({ ...nodeData, method });
    }
  }

  function validateParam(param) {
    if (!param.source) {
      return false;
    }
    if (!param.target) {
      return false;
    }
    return true;
  }

  function validate() {
    if (!nodeData.name) {
      message.error('节点名称不能为空');
      return false;
    }
    const method = nodeData.method;
    if (!method.methodCode) {
      message.error('服务接口不能为空');
      return false;
    }
    if (method.headerFillRules.length > 0 && !method.headerFillRules.every(validateParam)) {
      message.error('请求头赋值不完整');
      return false;
    }
    if (method.inputFillRules.length > 0 && !method.inputFillRules.every(validateParam)) {
      message.error('入参赋值不完整');
      return false;
    }
    if (method.outputFillRules.length > 0 && !method.outputFillRules.every(validateParam)) {
      message.error('出参赋值不完整');
      return false;
    }
    return true;
  }

  function onSubmit() {
    if (!validate()) {
      return;
    }
    onUpdate(cloneDeep(nodeData));
  }

  async function querySuiteList() {
    setSuiteLoading(true);
    const res = await suiteService.suiteList();
    if (res.success) {
      setSuiteList(res.result);
    }
    setSuiteLoading(false);
  }

  return (
    <div className="node-method-form">
      <Form form={form} layout="vertical">
        <Form.Item label="节点编码">
          <span>{nodeData.key}</span>
        </Form.Item>
        <Form.Item label="节点名称" required>
          <Input
            value={nodeData.name}
            onChange={(e) => setNodeData({ ...nodeData, name: e.target.value })}
            placeholder="请输入"
          />
        </Form.Item>
        <Form.Item label="节点描述">
          <TextArea
            value={nodeData.desc}
            onChange={(e) => setNodeData({ ...nodeData, desc: e.target.value })}
            placeholder="请输入"
            rows={2}
          />
        </Form.Item>
        <Form.Item label="套件" required>
          <Select
            value={nodeData.method.suiteCode}
            placeholder="请选择套件"
            style={{ width: '100%' }}
            onChange={onSuiteChange}
            loading={suiteLoading}
          >
            {suiteList.map((item) => (
              <Select.Option key={item.suiteCode} value={item.suiteCode}>
                {item.suiteName}
              </Select.Option>
            ))}
          </Select>
        </Form.Item>
        <Form.Item label="服务接口" required>
          <ApiSelect
            value={nodeData.method.methodCode}
            suiteCode={nodeData.method.suiteCode}
            onChange={onApiChange}
          />
        </Form.Item>
        <Form.Item label="请求头赋值">
          <InputRuleSetting
            value={nodeData.method.headerFillRules}
            onChange={(value) => setNodeData({ ...nodeData, method: { ...nodeData.method, headerFillRules: value } })}
            addText="新增请求头赋值"
            showRequired
            sourceList={headerSourceList}
            targetList={inputTargetList}
            requiredKeys={headerRequiredKeys}
          />
        </Form.Item>
        <Form.Item label="入参赋值">
          <InputRuleSetting
            value={nodeData.method.inputFillRules}
            onChange={(value) => setNodeData({ ...nodeData, method: { ...nodeData.method, inputFillRules: value } })}
            addText="新增入参赋值"
            showRequired
            sourceList={inputSourceList}
            targetList={inputTargetList}
            requiredKeys={inputRequiredKeys}
          />
        </Form.Item>
        <Form.Item label="出参赋值">
          <OutputRuleSetting
            value={nodeData.method.outputFillRules}
            onChange={(value) => setNodeData({ ...nodeData, method: { ...nodeData.method, outputFillRules: value } })}
            addText="新增出参赋值"
            sourceList={outputSourceList}
            targetList={outputTargetList}
          />
        </Form.Item>
        <Form.Item>
          <Button type="primary" onClick={onSubmit}>
            确定
          </Button>
          <Button onClick={onCancel}>取消</Button>
        </Form.Item>
      </Form>
    </div>
  );
};

export default MethodForm; 